package net.wanho.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import net.wanho.constant.UserConstant;
import net.wanho.dto.UserDTO;
import net.wanho.dto.UserModifyPwdDTO;
import net.wanho.dto.UserRoleDTO;
import net.wanho.entity.Role;
import net.wanho.entity.UserInfo;
import net.wanho.entity.UserRole;
import net.wanho.exception.UserErrorException;
import net.wanho.mapper.UserInfoMapper;
import net.wanho.mapper.UserRoleMapper;
import net.wanho.result.RoleEnum;
import net.wanho.service.UserInfoService;
import net.wanho.util.FileUtil;
import net.wanho.vo.PageVo;
import net.wanho.vo.UserVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author Administrator
* @description 针对表【user_info(用户表)】的数据库操作Service实现
* @createDate 2025-05-05 02:08:26
*/
@Service
@RequiredArgsConstructor
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService{
    @Value("${user.resetPwd}")
    private String resetPwd;

    private final UserRoleMapper userRoleMapper;

    @Override
    public PageVo<UserVo> getUserListPage(UserDTO userDTO, Integer pageNum, Integer pageSize) {
        IPage<UserInfo> page = new Page<>(pageNum, pageSize);

        List<UserVo> userVoList = baseMapper.selectUserList(page, userDTO);
        return new PageVo<>(
                page.getCurrent(),
                page.getSize(),
                page.getTotal(),
                page.getPages(),
                page.offset(),
                userVoList
        );
    }

    @Override
    public void saveUser(UserDTO userDTO) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getUserCode, userDTO.getUserCode())
                .eq(UserInfo::getIsDelete, UserConstant.USER_NOT_DELETED);
        if(ObjectUtil.isNotNull(baseMapper.selectOne(queryWrapper))) {
            throw new UserErrorException("用户名已存在！");
        }

        UserInfo userInfo = new UserInfo();
        BeanUtil.copyProperties(userDTO, userInfo);
        userInfo.setUserPwd(MD5.create().digestHex(userDTO.getUserPwd()));
        userInfo.setUserState("1");
        userInfo.setIsDelete("0");

        save(userInfo);

        // 默认普通用户
        userRoleMapper.insert(new UserRole(RoleEnum.USER.getCode(), userInfo.getUserId()));
    }

    @Override
    public void updateUserById(Integer id) {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(id);
        userInfo.setIsDelete("1");

        updateById(userInfo);
    }

    @Override
    public void removeUserBatchByIds(List<Integer> ids) {
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(UserInfo::getUserId, ids)
                .set(UserInfo::getIsDelete, "1");

        update(updateWrapper);
    }

    @Override
    public void updatePwdById(Integer id) {
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>() ;
        updateWrapper.eq(UserInfo::getUserId, id)
                .set(UserInfo::getUserPwd, MD5.create().digestHex(resetPwd));

        update(updateWrapper);
    }

    @Override
    public void assignRole(UserRoleDTO userRoleDTO) {
        // 新的角色列表
        List<Integer> newUserRoleIdList = userRoleDTO.getRoleList().stream()
                .filter(role -> userRoleDTO.getRoleCheckList().contains(role.getRoleName()))
                .mapToInt(Role::getRoleId)
                .boxed().collect(Collectors.toList());
        // 旧的角色列表
        List<Integer> oldUserRoleIdList = userRoleMapper.selectList(new LambdaQueryWrapper<UserRole>()
                .eq(UserRole::getUserId, userRoleDTO.getUserId()))
                .stream().mapToInt(UserRole::getRoleId)
                .boxed().collect(Collectors.toList());
        // 需要删除的角色列表
        List<Integer> deleteUserRoleIdList = oldUserRoleIdList.stream()
                .filter(roleId -> !newUserRoleIdList.contains(roleId))
                .collect(Collectors.toList());
        // 删除未分配的角色
        if(ObjectUtil.isNotEmpty(deleteUserRoleIdList)) {
            userRoleMapper.delete(new LambdaQueryWrapper<UserRole>()
                    .eq(UserRole::getUserId, userRoleDTO.getUserId())
                    .in(UserRole::getRoleId, deleteUserRoleIdList));
        }

        // 需要新增的角色列表
        List<Integer> addUserRoleIdList = newUserRoleIdList.stream()
                .filter(roleId -> !oldUserRoleIdList.contains(roleId))
                .collect(Collectors.toList());

        // 新增分配的角色
        if(ObjectUtil.isNotEmpty(addUserRoleIdList)) {
            addUserRoleIdList.forEach(roleId -> userRoleMapper.insert(new UserRole(roleId, userRoleDTO.getUserId())));
        }
    }

    @Override
    public void modifyUserPwd(UserModifyPwdDTO userModifyPwdDTO) {
        String newUserPwd = MD5.create().digestHex(userModifyPwdDTO.getPassword());
        String oldUserPwd = MD5.create().digestHex(userModifyPwdDTO.getOldPassword());

        if (ObjectUtil.notEqual(oldUserPwd, baseMapper.selectById(userModifyPwdDTO.getId()).getUserPwd())) {
            throw new UserErrorException("旧密码输入错误！");
        }

        if(ObjectUtil.notEqual(userModifyPwdDTO.getPassword(), userModifyPwdDTO.getRepeatPassword())) {
            throw new UserErrorException("两次输入的密码不一致！");
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userModifyPwdDTO.getId());
        userInfo.setUserPwd(newUserPwd);

        updateById(userInfo);
    }

    @Override
    public String modifyAvatar(Integer id, MultipartFile file) {
        UserInfo userInfo = getById(id);
        String path = FileUtil.uploadFIle(file);
        if (StringUtils.isBlank(path)) {
            throw new UserErrorException("上传头像失败");
        }
        userInfo.setAvatar(path);
        updateById(userInfo);
        return path;
    }
}




